<?php

// +----------------------------------------------------------------------+
// | PHP version 5                                                        |
// +----------------------------------------------------------------------+
// | Placed in public domain by Allan Hansen, 2003. Share and enjoy!      |
// |                                                                      |
// | Class inspired by DB_Sql class from  http://phplib.netuse.de/        |
// +----------------------------------------------------------------------+
// | Updates and other scripts by Allan Hansen here:                      |
// |     http://www.artemis.dk/php/                                       |
// |                                                                      |
// | Similar abstraction layers for other databases are avalible there.   |
// +----------------------------------------------------------------------+
// | mysql.php                                                            |
// | MySQL Abstraction Layer.                                             |
// +----------------------------------------------------------------------+
// | Authors: Allan Hansen <ah@artemis.dk>                                |
// +----------------------------------------------------------------------+
//
// $Id: mysql.php,v 1.1.1.1 2004/08/21 21:59:06 ah Exp $





/**
* MySQL Abstraction Layer.
*/

class mysql 
{

    // public: connect variables
    public $hostname;
    public $database;
    public $username;
    public $password;
    public $persistent; 
    
    // private variables
    private $auto_commit = true;
    private $transaction = false;
    private $connection  = false;
    private $cursor      = false;
    private $record      = array();
    
    // constants related to mysql - used dbObject
    const field_quote      = "`";
    const table_quote      = "`";   
    const ping_string      = "''";
    const support_auto_inc = true;
    


    /**
    * Contructor
    *
    * @param    string  query   SQL query to run immediately.
    */

    public function __construct($query = false)
    {
        // Make sure that php has mysql support
        if (!function_exists("mysql_pconnect")) {
            die("PHP not compiled with mysql support.");
        }

        if ($query) {
            $this->query($query);
        }
    }
    
    
    
    /**
    * Destructor.
    */
    
    public function __destuct()
    {
        // Destroy cursor
        $this->free();
        
        // Unset connection - garbage collector will take care of the rest
        unset($this->connection);
    }



    /**
    * Connect to mysql server.
    *
    * @return   int                 mysql connection or false
    */

    public function connect()
    {
        // Establish connection, select database
        if (!$this->connection) {

            // Connect
            $connect_function = $this->persistent ? "mysql_pconnect" : "mysql_connect";
            $this->connection = @$connect_function($this->hostname, $this->username, $this->password, true);
            if (!$this->connection) {
                return $this->halt("connect() failed.");
            }
            
            // Select database
            if (!@mysql_select_db($this->database, $this->connection)) {
                return $this->halt("Cannot use database $this->database");
            }
        }

        return $this->connection;
    }



    /**
    * Discard the query result / cursor.
    */

    public function free()
    { 
        @mysql_free_result($this->cursor);
        $this->cursor = false;
    }



    /**
    * Perform a query.
    *
    * @param    string  query   SQL query.
    * @return   int             mysql cursor or false
    */

    public function query($query)
    {
        // No empty queries
        if (empty($query)) {
            return;
        }
        
        //echo "<hr>$query<br>";

        // Connect if not already
        if (!$this->connect()) {
            return;
        }
     
        // New query, discard previous result.
        if ($this->cursor) {
            $this->free();
        }

        // Perform query
        $this->cursor = @mysql_query($query, $this->connection);
        
        // Error handling - mysql errors - i.e. duplicate key
        if (mysql_errno($this->connection)) {
            $this->error =  mysql_errno($this->connection) . ": " . mysql_error($this->connection);
        }        
        
        // Error handling - invalid queries
        if (!$this->cursor) {
            return $this->halt("Invalid SQL: $query");
        }
        
        // Success - return cursor
        return $this->cursor;
    }



    /**
    * Walk result set.
    *
    * @return   bool           Success
    */

    public function next_record()
    {
        // No pending query
        if (!$this->cursor) {
            return $this->halt("next_record() called with no query pending.");
        }

        // Fetch
        $this->record = @mysql_fetch_array($this->cursor);
        
        // Handle EOD/error
        if (!is_array($this->record)) {
            
            // Handle error
            if (mysql_errno($this->connection)) {
                $this->error =  mysql_errno($this->connection) . ": " . mysql_error($this->connection);
            }
            
            // Autofree
            $this->free();
        }

        // Return success
        return is_array($this->record);
    }



    /**
    * Number of affected rows, last SQL operation.
    */

    public function affected_rows()
    {
        return @mysql_affected_rows($this->connection);
    }



    /**
    * Number of rows in result set.
    */

    public function num_rows()
    {
        return @mysql_num_rows($this->cursor);
    }



    /**
    * Number of fields in result set.
    */

    public function num_fields()
    {
        return @mysql_num_fields($this->cursor);
    }



    /**
    * Value of field in result set.
    */

    public function f($name)
    { 
        return $this->record[$name];
    }



    /**
    * Insert id from AutoIncrement, last insert operation.
    */

    public function insert_id()
    {
        return @mysql_insert_id ($this->connection);
    }



    /**
    * Begin transaction.
    *
    * @return   bool                 Success
    */

    public function begin()
    {
        // transaction already begun
        if ($this->transaction) {
            return;
        }
        
        if ($this->auto_commit) {
            $this->auto_commit = false;
            if (!$this->query("set autocommit=0")) {
                return;
            }
        }
        
        if (!$this->query("begin")) {
            return;
        }        
        $this->transaction = true;
        return true;
    }



    /**
    * Commit transaction.
    *
    * @return   bool                 Success
    */

    public function commit()
    {
        // transaction not begun
        if (!$this->transaction) {
            return;
        }
        
        if (!$this->query("commit")) {
            return;
        }
        $this->transaction = false;
        return true;
    }



    /**
    * Rollback transaction.
    *
    * @return   bool                 Success
    */

    public function rollback()
    { 
        // transaction not begun
        if (!$this->transaction) {
            return;
        }
        
        if (!$this->query("rollback")) {
            return;
        }
        $this->transaction = false;
        return true;
    }
    
    
    
    /**
    * Return array of tables names
    *
    * @return   array of string     Table names
    */
    
    public function tables()
    {
        $this->query("show tables");
        
        $result = array ();
        
        while ($this->next_record()) {
            $result[] = $this->record[0];
        }
        
        return $result;
    }
    
    
    
    /**
    * Get table meta data.
    *
    * @param    string  table       Table to show. If false, use query result.
    */

    public function metadata($table = false)
    {
        // Connect if not already
        $this->connect();
    
        // Init
        $count  = 0;
        $id     = 0;
        $result = array();

        // From table
        if ($table) {
            $id = @mysql_list_fields($this->database, $table);
            if (!$id) {
                return $this->halt("Metadata query failed.");
            }
        }
        
        // From query result
        else {
            $id = $this->cursor;
            if (!$id) {
                return $this->halt("No query specified.");
            }
        }

        $count = @mysql_num_fields($id);

        // Build result
        for ($i=0; $i<$count; $i++) {
            $result[$i]["table"] = @mysql_field_table ($id, $i);
            $result[$i]["name"]  = @mysql_field_name  ($id, $i);
            $result[$i]["type"]  = @mysql_field_type  ($id, $i);
            $result[$i]["len"]   = @mysql_field_len   ($id, $i);
            $result[$i]["flags"] = @mysql_field_flags ($id, $i);
        }

        // Free the if we were called on a table
        if ($table) {
            @mysql_free_result($id);
        }

        // Return
        return $result;
    }



    /**
    * Halt and produce error handling.
    */

    private function halt($msg)
    {
        $this->error = @mysql_errno($this->connection) . ": " . @mysql_error($this->connection);
        
        // Rollback transaction if applicable
        if ($this->transaction) {
            $this->rollback();
        }
        
        throw new mysql_exception('<b>' . $msg . '</b> caused mysql error: <b>'.$this->error . '</b>');
        
        return false;
    }

}




/**
* MySQL Abstraction Layer Exception Class.
*/

class mysql_exception extends Exception
{
    public $message;
}


?>